#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#include <unistd.h>
#include <asm/types.h>  // 补充这一行，包含一些基本类型定义，有时候PF_NL相关的类型也依赖它

#define NETLINK_USER 31
#define MAX_PAYLOAD 1024

int main() {
    int sock_fd;
    struct sockaddr_nl src_addr, dest_addr;
    struct nlmsghdr *nlh = NULL;
    struct iovec iov;
    struct msghdr msg;

    sock_fd = socket(PF_NL, SOCK_RAW, NETLINK_USER);
    if (sock_fd < 0) {
        perror("socket");
        return -1;
    }

    memset(&src_addr, 0, sizeof(src_addr));
    src_addr.nl_family = AF_NETLINK;
    src_addr.nl_pid = getpid();
    bind(sock_fd, (struct sockaddr *)&src_addr, sizeof(src_addr));

    memset(&dest_addr, 0, sizeof(dest_addr));
    dest_addr.nl_family = AF_NETLINK;
    dest_addr.nl_pid = 0;
    dest_addr.nl_groups = 0;

    nlh = (struct nlmsghdr *)malloc(NLMSG_SIZEOF(0));
    nlh->nlmsg_len = NLMSG_SIZEOF(0);
    nlh->nlmsg_pid = getpid();
    nlh->nlmsg_flags = 0;

    iov.iov_base = (void *)nlh;
    iov.iov_len = nlh->nlmsg_len;

    msg.msg_name = (void *)&dest_addr;
    msg.msg_namelen = sizeof(dest_addr);
    msg.msg_iov = &iov;
    msg.msg_iovlen = 1;
    msg.msg_control = NULL;
    msg.msg_controllen = 0;
    msg.msg_flags = 0;

    // 发送订阅请求，这里简单示意，实际可能更复杂
    sendmsg(sock_fd, &msg, 0);

    while (1) {
        // 接收内核消息
        recvmsg(sock_fd, &msg, 0);
        nlh = (struct nlmsghdr *)msg.msg_iov[0].iov_base;
        if (nlh->nlmsg_type == NLMSG_DONE) {
            break;
        }
        printf("Received message from kernel: %s\n", (char *)NLMSG_DATA(nlh));
    }

    close(sock_fd);
    free(nlh);
    return 0;
}